#pragma once
#include <Windows.h>
#include "core/CTimer.h"
#include "Math/RetroMath.h"

class CDirect3D;
class CRetroInput;
class CStateMachine;
typedef void(*GameFunctor)(void*);

// struct for game settings
struct GameSettings
{
	bool	invertX;
	bool	invertY;
	float	sensitivityX;
	float	sensitivityY;

};

class CGame
{
private: // singleton
	CGame(void);
	~CGame(void);
	CGame(const CGame&);
	CGame& operator=(const CGame&);
	static CGame* m_pInstance;
public: // singleton
	static CGame* GetInstance();
	static void DestroyInstance();
private: // (data)structures
	struct FunctionCallList
	{
		GameFunctor function;
		void* pArgument;
		FunctionCallList* pNext;
	};
private: // variables

	// status/ debug
	bool	m_bRunning;
	int		m_nFPS;
	double	m_dblFrameRenderTime;
	bool	m_bShowFPS;
	FunctionCallList* m_pFunctionCalls;

	// game window
	HWND m_hWnd;
	HINSTANCE m_hInstance;
	public:
	int m_nWindowWidth;
	int m_nWindowHeight;
	private:
	// for timing
	CTimer m_Timer;
	double m_dblPrevElapsedTime;

	// core runtime things
	CDirect3D* m_pRender;
	CRetroInput* m_pInput;
	CStateMachine* m_pStateMachine;

	// global things needed 
	GameSettings m_Settings;
	vec3<float> m_vfCursorPosition;
	GameFunctor UpdateCursorFunction;


private: // functions
	void InitSettings();
	void AddFunctionCall(GameFunctor function, void* pArgument);
	void FlushFunctionCalls();
	void CallFunctionCalls();
	static void ShowFPS(void* pGame);
	static void ShowCursorPosition(void* pGame);
	static void ShowAccelerometer(void* pGame);
	static void ShowMotionPlus(void* pGame);
	static void ShowWiiButtonBits(void* pGame);
	static void CursorByMouse(void* pGame);
	static void CursorByWiimote(void* pGame);
public: // accessors/modifyers
	inline const bool IsRunning() { return m_bRunning; }
	inline const int GetFPS() { return m_nFPS;}
	inline const double GetFrameRenderTime_Double() { return m_dblFrameRenderTime;}
	inline const float GetFrameRenderTime_Single() { return static_cast<float>(m_dblFrameRenderTime);}
	inline const vec3<float>& GetCursorPosition() { return m_vfCursorPosition;}
public: // functions

	bool Initialize(HWND hWnd, HINSTANCE hInstance, int nWindowWidth, int nWindowHeight);
	void Update();
	void Shutdown();

	void CenterCursorPosition();
	void SetCursorDevicePriority(BYTE deviceCode);

};

